<?php
namespace app\api\services;

use app\api\consDir\ErrorConst;
use app\api\consDir\SupplyConst;
use app\common\libs\Singleton;
use app\common\models\Order\Order;
use app\common\models\Order\OrderExpress;
use app\common\models\Order\OrderGoods;
use app\common\models\Order\OrderShop;
use app\common\models\Supply\SupplyCate;
use app\common\models\Supply\SupplyGoods;
use app\common\models\Supply\SupplySku;
use app\common\utils\CommonUtil;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;

class SupplyService
{
    use Singleton;

    /**
     * @throws ModelNotFoundException
     * @throws DbException
     * @throws DataNotFoundException
     */
    public function goodsCategory($categoryId): array
    {
        $where = [
            ['pid', '=', $categoryId],
            ['status', '=', 0],
            ['deleted', '=', 0],
        ];
        $category = SupplyCate::getInstance()
            ->where($where)
            ->field('*')
            ->order('sort desc')
            ->select();
        return empty($category) ? [] : $category->toArray();
    }

    /**
     * @throws ModelNotFoundException
     * @throws DataNotFoundException
     * @throws DbException
     */
    public function goodsList($page, $pageSize, $keyword, $categoryId1, $categoryId2, $categoryId3, $sort, $positionType = 0): array
    {
        $where = [
            ['status', '=', 0],
            ['deleted', '=', 0],
        ];
        if ($keyword) {
            $where[] = ['name', 'like', '%' . $keyword . '%'];
        }
        if ($categoryId1) {
            $where[] = ['category_id1', '=', $categoryId1];
        }
        if ($categoryId2) {
            $where[] = ['category_id2', '=', $categoryId2];
        }
        if ($categoryId3) {
            $where[] = ['category_id3', '=', $categoryId3];
        }
        if($positionType){
            $where[] = ['position_type', '=', $positionType];
        }

        //$arr   = ['sell_price desc', 'sell_price asc', 'goods_sales desc', 'goods_sales asc'];
        //$order = $arr[$sort] ?? $arr[1];
        //$order = $arr[$sort] ?? 'sort desc';

        /*if ($positionType == 1) {
            $order = 'sort desc,position_type desc, sort desc,id desc';
        }*/
        $field = [
            'id',
            'carousel_img_list',
            'inventory',
            'name',
            'spu_id',
            'sell_price',
            'market_price',
            'gxz_rate',
            'goods_tag',
            'goods_service',
            'cover_img',
        ];
        $supplyGoods = SupplyGoods::getInstance()
            ->where($where)
            ->field($field)
            ->order('sort desc,sell_price asc,id desc')
            ->page($page, $pageSize)
            ->select();
        // echo SupplyGoods::getInstance()->getlastsql();exit;
        return empty($supplyGoods) ? [] : $supplyGoods->toArray();
    }

    /**
     * @throws ModelNotFoundException
     * @throws DataNotFoundException
     * @throws DbException
     */
    public function goodsDetail($id): array
    {
        $detail = SupplyGoods::getInstance()->where('id', $id)->find();
        $detail = empty($detail) ? [] : $detail->toArray();
        if ( ! empty($detail)) {
            $detail['goodsTag']        = empty($detail['goodsTag']) ? [] : json_decode($detail['goodsTag'], true);
            $detail['goodsService']    = empty($detail['goodsService']) ? [] : json_decode($detail['goodsService'], true);
            $detail['carouselImgList'] = $detail['carouselImgList'] ? explode(',', $detail['carouselImgList']) : [];
        }
        return $detail;
    }

    public function getOrderDetail($orderSn)
    {
        $data = [
            'orderSn' => $orderSn,
        ];
        return $this->getData(SupplyConst::GET_ORDER_DETAIL, $data);
    }

    public function getRegionByCodeOpen($regionCode = '')
    {
        $data = [
            'regionQueryDTO' => [],
        ];
        if ($regionCode) {
            $data = [
                'regionCode' => $regionCode,
            ];
        }
        return $this->getData(SupplyConst::GET_REGION_BY_CODE_OPEN, $data);
    }

    /**
     * @throws ModelNotFoundException
     * @throws DataNotFoundException
     * @throws DbException
     */
    public function orderPreview($spuInfoList): array
    {
        $list = json_decode($spuInfoList, true);
        $data = [];
        foreach ($list as $v) {
            $goods           = SupplyGoods::getInstance()->where('spu_id', $v['spuId'])->find();
            $sku             = SupplySku::getInstance()->where('sku_id', $v['skuId'])->find();
            $skuPropertyList = json_decode($sku['skuPropertyList'], true);
            if (empty($skuPropertyList)) {
                CommonUtil::throwException(
                    ErrorConst::NO_GOODS_ERROR,
                    ErrorConst::NO_GOODS_ERROR_MSG,
                );
            }
            $specValueName = array_column($skuPropertyList, 'specValueName');
            $data[]        = [
                'goodsId'     => $goods['id'],
                'name'        => $goods['name'],
                'img'         => $goods['coverImg'],
                'quantity'    => $v['quantity'],
                'marketPrice' => $sku['officialDistriPrice'],
                'sellPrice'   => $sku['suggestPrice'],
                'basePrice'   => $sku['basePrice'],
                'skuPicUrl'   => $sku['skuPicUrl'],
                'skuId'       => $sku['id'],
                'skuTitle'    => implode(';', $specValueName),
                'spuId'       => $v['spuId'],
                'stock'       => $sku['stock'],
                'gxzRate'     => $goods['gxzRate'],
            ];
        }
        return $data;
    }

    /**
     * 查询商品运费
     * @param $spuInfoList
     * @param $cityId
     * @return mixed
     */
    public function freight($spuInfoList, $cityId)
    {
        $data = [
            "spuInfoList" => json_decode($spuInfoList, true),
            "cityId"      => $cityId,
        ];
        return $this->getData(SupplyConst::FREIGHT_CALCULATE, $data);
    }

    /**
     * 查询商品价格
     * @param $skuIds
     * @return mixed
     */
    public function findSkuSalePrice($skuIds)
    {
        $data = [
            'skuIds' => $skuIds,
        ];
        return $this->getData(SupplyConst::FIND_SKU_SALE_PRICE, $data);
    }

    /**
     * 查询商品库存
     * @param $skuIdList
     * @return mixed
     */
    public function findSkuStock($skuIdList)
    {
        $data = [
            'skuIdList' => $skuIdList,
        ];
        return $this->getData(SupplyConst::FIND_SKU_STOCK, $data);
    }

    /**
     * 根据外部订单号查询订单详情列表
     * @param $thirdOrderSn
     * @return mixed
     */
    public function getOrderDetailList($thirdOrderSn)
    {
        $data = [
            'thirdOrderSn' => $thirdOrderSn,
        ];
        return $this->getData(SupplyConst::GET_ORDER_DETAIL_LIST, $data);
    }

    /**
     * 创建订单
     * @param $goodsList
     * @param $shipName
     * @param $shipAddress
     * @param $shipMobile
     * @param $shipAreaCode
     * @param $outOrderSn
     * @return mixed
     */
    public function submitOrder($goodsList, $shipName, $shipAddress, $shipMobile, $shipAreaCode, $outOrderSn)
    {
        $data = [
            'orderSource'  => 1,
            'goodsList'    => json_decode($goodsList, true),
            'shipName'     => $shipName,
            'shipAddress'  => $shipAddress,
            'shipMobile'   => $shipMobile,
            'shipAreaCode' => $shipAreaCode,
            'outOrderSn'   => $outOrderSn,
        ];
        //Log::error('供应链下单请求参数:' . json_encode($data));
        return $this->getData(SupplyConst::SUBMIT_ORDER, $data);
    }

    public function messagePoolList()
    {
        $data = [
            'messagePoolLogQto' => [],
        ];
        return $this->getData(SupplyConst::MESSAGE_POOL_LIST, $data);
    }

    /**
     * 分销商-申请售后
     * https://sce-opc.changecloud.cn/#/passport/api-service
     * @param $reason 退费原因
     * @param $orderSn 订单编号
     * @param $refundReasonId 退款原因ID, 请参考文档中心-订单售后申请原因说明文档
     *                                    1-退款 （订单发货前） 19   其他
     *                                    2-退货退款（订单发货后） 24 其他
     *                                    3-换货（订单发货后） 29 其他
     *                                    4-仅退款（订单发货后）40 其他
     * @param $returnType 售后类型，1：退款，2：退货退款，3：换货，4：仅退款，5：部分退款
     * @param $goodsList [['goodsQuantity'=>1, 'goodsSpecId'=>'']]
     * @return mixed
     */
    public function applyRefund($reason, $orderSn, $refundReasonId, $returnType, $goodsList)
    {
        $data = [
            'reason'         => $reason,
            'orderSn'        => $orderSn,
            'refundReasonId' => $refundReasonId,
            'goodsList'      => $goodsList,
            'returnType'     => $returnType,
        ];
        return $this->getData(SupplyConst::APPLY_REFUND, $data);
    }

    public function cancelRefund($returnSn)
    {
        $data = [
            'returnSn' => $returnSn,
        ];
        return $this->getData(SupplyConst::CANCEL_REFUND, $data);
    }

    /**
     * 查询售后单详细信息
     * @param $returnSn
     * @return mixed
     */
    public function orderRefundDetail($returnSn)
    {
        $data = [
            'returnSn' => $returnSn,
        ];
        return $this->getData(SupplyConst::ORDER_RETURN_GOODS, $data);
    }

    /**
     * 退货/换货邮寄卖家
     * https://sce-opc.changecloud.cn/#/passport/api-service
     * @param $deliverySn 物流单号
     * @param $deliveryCorpName 物流公司名称
     * @param $returnSn 售后单号
     * @return mixed
     */
    public function sendReturnGoods($deliverySn, $deliveryCorpName, $returnSn)
    {
        $data = [
            'deliverySn'       => $deliverySn,
            'deliveryCorpName' => $deliveryCorpName,
            'returnSn'         => $returnSn,
        ];
        return $this->getData(SupplyConst::SEND_RETURN_GOODS, $data);
    }

    /**
     * 修改订单
     * @throws DataNotFoundException
     * @throws ModelNotFoundException
     * @throws DbException
     */
    public function changeOrder($order): bool
    {
        $ret = SupplyService::getInstance()->getOrderDetailList($order['orderNo']);
        if ($ret['status'] != 200 || empty($ret['data'])) {
            return false;
        }
        $orderExpressData = [];
        foreach ($ret['data'] as $vv) {
            //订单状态: 10-已提交待付款,20-已付款待发,30-已发货待收货,40-确认收货交易成功,50-用户超时未支付订单自动取消,70-订单发货前售后关闭,80-订单发货后售后关闭
            if ($vv['orderStatus'] != 30) {
                continue;
            }
            //更新状态 更新物流信息
            $order->status     = 2;
            $order->update_at  = date('Y-m-d H:i:s');
            $order->deliver_at = $vv['sendTime'];
            $order->save();
            OrderGoods::getInstance()
                ->where('order_no', $order['orderNo'])
                ->update(['status' => 2]);
            if (empty($vv['deliverList'])) {
                continue;
            }
            foreach ($vv['deliverList'] as $deliver) {
                foreach ($deliver['orderExpressItemVOList'] as $expressItem) {
                    $supplyGoods = SupplyGoods::getInstance()
                        ->where('spu_id', $expressItem['goodsId'])
                        ->find();
                    $where = [
                        'order_no' => $order['orderNo'],
                        'goods_id' => $supplyGoods['id'],
                    ];
                    $supplyOrderGoods   = OrderGoods::getInstance()->where($where)->find();
                    $orderExpressData[] = [
                        'express_no'     => $deliver['deliverySn'],
                        'express_name'   => $deliver['expressName'],
                        'user_id'        => $order['userId'],
                        'order_no'       => $order['orderNo'],
                        'goods_id'       => $supplyGoods['id'],
                        'goods_order_id' => $supplyOrderGoods['id'],
                    ];
                }
            }
        }
        if ( ! empty($orderExpressData)) {
            OrderExpress::getInstance()->insertAll($orderExpressData);
        }
        return true;
    }

    public function changeOnlineOrder($orderGoods): bool
    {
        $ret = SupplyService::getInstance()->getOrderDetailList($orderGoods['orderNo']);
        if ($ret['status'] != 200 || empty($ret['data'])) {
            return false;
        }
        $orderExpressData = [];
        foreach ($ret['data'] as $vv) {
            //订单状态: 10-已提交待付款,20-已付款待发,30-已发货待收货,40-确认收货交易成功,50-用户超时未支付订单自动取消,70-订单发货前售后关闭,80-订单发货后售后关闭
            if ($vv['orderStatus'] != 30) {
                continue;
            }
            $where = [
                'order_no' => $orderGoods['orderNo'],
                'status' => 1
            ];
            $order = Order::getInstance()->where($where)->find();
            if(empty($order)){
                continue;
            }
            if (empty($vv['deliverList'])) {
                continue;
            }
            //更新状态 更新物流信息
            $order->status     = 2;
            $order->update_at  = date('Y-m-d H:i:s');
            $order->deliver_at = $vv['sendTime'];
            $order->save();
            OrderGoods::getInstance()
                ->where('order_no', $order['orderNo'])
                ->update(['status' => 2,'deliver_at' => date('Y-m-d H:i:s')]);
            OrderShop::getInstance()->where('order_no', $order['orderNo'])->update(['status' => 2,'deliver_at' => date('Y-m-d H:i:s')]);
            foreach ($vv['deliverList'] as $deliver) {
                $orderExpressData[] = [
                    'express_no'     => $deliver['deliverySn'],
                    'express_name'   => $deliver['expressName'],
                    'user_id'        => $order['userId'],
                    'order_no'       => $order['orderNo'],
                    'goods_id'       => $orderGoods['goodsId'],
                    'goods_order_id' => $orderGoods['id'],
                ];
            }
        }
        if ( ! empty($orderExpressData)) {
            OrderExpress::getInstance()->insertAll($orderExpressData);
        }
        return true;
    }

    public function changeExchangeOrder($order): bool
    {
        $ret = SupplyService::getInstance()->getOrderDetailList($order['orderNo']);
        if ($ret['status'] != 200 || empty($ret['data'])) {
            return false;
        }
        $orderExpressData = [];
        foreach ($ret['data'] as $vv) {
            //订单状态: 10-已提交待付款,20-已付款待发,30-已发货待收货,40-确认收货交易成功,50-用户超时未支付订单自动取消,70-订单发货前售后关闭,80-订单发货后售后关闭
            if ($vv['orderStatus'] != 30) {
                continue;
            }
            //更新状态 更新物流信息
            $order->status     = 2;
            $order->update_at  = date('Y-m-d H:i:s');
            $order->deliver_at = $vv['sendTime'];
            $order->save();
            \app\common\models\ExchangeOrderGoods::getInstance()
                ->where('order_no', $order['orderNo'])
                ->update(['status' => 2]);
            if (empty($vv['deliverList'])) {
                continue;
            }

            foreach ($vv['deliverList'] as $deliver) {
                foreach ($deliver['orderExpressItemVOList'] as $expressItem) {
                    $supplyGoods = SupplyGoods::getInstance()
                        ->where('spu_id', $expressItem['goodsId'])
                        ->find();
                    $where = [
                        'order_no' => $order['orderNo'],
                        'goods_id' => $supplyGoods['id'],
                    ];
                    $supplyOrderGoods = \app\common\models\ExchangeOrderGoods::getInstance()
                        ->where($where)
                        ->find();
                    $orderExpressData[] = [
                        'express_no'     => $deliver['deliverySn'],
                        'express_name'   => $deliver['expressName'],
                        'user_id'        => $order['userId'],
                        'order_no'       => $order['orderNo'],
                        'goods_id'       => $supplyGoods['id'],
                        'goods_order_id' => $supplyOrderGoods['id'],
                    ];
                }
            }
        }
        if ( ! empty($orderExpressData)) {
            \app\common\models\ExchangeOrderExpress::getInstance()
                ->insertAll($orderExpressData);
        }
        return true;
    }

    /**
     * 更新商品
     * @throws DbException
     */
    public function updateGoods($spuIds): bool
    {
        $ret = SupplyService::getInstance()->getData(SupplyConst::GET_SPU_BY_SPUIDS, ['spuIdList' => $spuIds]);
        if ($ret['status'] != 200 || empty($ret['data'])) {
            return false;
        }
        foreach ($ret['data'] as $v) {
            foreach ($v as $kk => $vv) {
                if (is_array($vv)) {
                    $v[$kk] = json_encode($vv, 256);
                }

            }
            $v     = CommonUtil::camelToUnderLine($v);
            unset($v['lib_name'],$v['lib_type']);
            $count = SupplyGoods::getInstance()->where('spu_id', $v['spu_id'])->count();
            if ($count == 0) {
                SupplyGoods::getInstance()->insert($v);
            } else {
                SupplyGoods::getInstance()->where('spu_id', $v['spu_id'])->update($v);
            }
            $skuList = SupplyService::getInstance()->getData(SupplyConst::LIST_SKU_BY_SPU_ID, ['spuId' => $v['spu_id']]);
            if ($skuList['status'] != 200 || empty($skuList['data'])) {
                continue;
            }
            //sku
            $marketPrice = 0;
            $sellPrice   = 0;
            foreach ($skuList['data'] as $skuK => $skuV) {
                foreach ($skuV as $kk => $vv) {
                    if (is_array($vv)) {
                        $skuV[$kk] = json_encode($vv, 256);
                    }
                }
                if ($skuK == 0) {
                    $marketPrice = $skuV['officialDistriPrice'];
                    $sellPrice   = $skuV['suggestPrice'];
                }
                $marketPrice = min($marketPrice, $skuV['officialDistriPrice']);
                $sellPrice   = min($sellPrice, $skuV['suggestPrice']);

                $skuV           = CommonUtil::camelToUnderLine($skuV);
                $count          = SupplySku::getInstance()->where('sku_id', $skuV['sku_id'])->count();
                $skuV['spu_id'] = $v['spu_id'];
                if ($count == 0) {
                    SupplySku::getInstance()->insert($skuV);
                } else {
                    SupplySku::getInstance()->where('sku_id', $skuV['sku_id'])->update($skuV);
                }
            }
            SupplyGoods::getInstance()->where('spu_id', $v['spu_id'])->update(['market_price' => $marketPrice, 'sell_price' => $sellPrice]);

        }
        return true;
    }

    /**
     * 删除商品
     * @param $spuId
     * @return bool
     */
    public function delGoods($spuId): bool
    {
        SupplyGoods::getInstance()->where('spu_id', $spuId)->update(['deleted' => 1]);
        return true;
    }

    /**
     * @throws ModelNotFoundException
     * @throws DbException
     * @throws DataNotFoundException
     */
    public function getCollectList($ids): array
    {
        $where = [
            ['id', 'in', $ids],
        ];
        $ret = SupplyGoods::getInstance()->where($where)->field('id,name as goods_title,carousel_img_list,market_price,sell_price,cover_img as goods_img')->select();
        if ( ! empty($ret)) {
            $ret = $ret->toArray();
            foreach ($ret as &$v) {
                $v = CommonUtil::camelToUnderLine($v);
            }
            return $ret;
        } else {
            return [];
        }
    }

    public function getData($url, $body)
    {
        $url    = SupplyConst::DOMAIN . $url;
        $header = [
            'appKey'       => config('supply.appKey'),
            'timeStamp'    => round(microtime(true) * 1000),
            'randomNumber' => rand(100000, 999999),
            'version'      => config('supply.version'),
        ];
        $header         = array_merge($header, $body);
        $header['sign'] = $this->getSign($header);
        \think\facade\Log::info('supply_post_before ' . $url . " / post_data " . json_encode($body, 320));
        $ret = $this->curlPost($url, $header, $body);
        \think\facade\Log::info('supply_post_after ' . $url . " / result " . $ret);

        return json_decode($ret, true);
    }

    public function curlPost($url, $header = [], $post_data = [])
    {
        $newHeader[] = "Content-type:application/json";
        foreach ($header as $k => $v) {
            if (is_array($v)) {
                $v = json_encode($v);
            }

            $newHeader[] = $k . ":" . $v;
        }
        $post_data = json_encode($post_data);
        $ch        = curl_init();
        curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $newHeader);
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        $output = curl_exec($ch);
        curl_close($ch);
        return $output;
    }

    /**
     * 获取签名
     * @param array $data
     * @param string $buff
     * @return string
     */
    public function getSign(array $data, string $buff = ''): string
    {
        ksort($data);
        if (isset($data['sign'])) {
            unset($data['sign']);
        }

        foreach ($data as $k => $v) {
            if (is_array($v)) {
                $v = json_encode($v);
            }

            $buff .= "{$k}={$v}&";
        }
        $buff = $buff . config('supply.AppSecret');
        return hash('md5', $buff);
    }
}
